package com.xwaf.platform.web.config.shiro;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xwaf.platform.common.api.entity.TokenInfo;
import com.xwaf.platform.system.api.entity.auth.User;
import com.xwaf.platform.system.api.request.auth.TokenVerifyRequest;
import com.xwaf.platform.system.api.service.auth.PermissionModuleService;
import com.xwaf.platform.system.api.service.auth.UserService;
import com.xwaf.platform.system.api.service.gateway.TokenService;

/**
 * 
 * <p>
 * 认证
 * <p>
 * 
 * @author 李聪 <br>
 * @email xwaf_love@yeah.net <br>
 * @since JDK 1.8<br>
 * @date 2019年12月30日 上午9:17:52 <br>
 * @see 无<br>
 *      Copyright (c) 2019, xwaf_love@yeah.net All Rights Reserved.<br>
 */
@Component
public class OAuth2Realm extends AuthorizingRealm {

	private static final Logger log = LoggerFactory.getLogger(OAuth2Realm.class);

	private static List<String> ALL_FUNCTION = null;
	private static List<String> ALL_MODULE = null;
	private static List<String> ALL_FIELD = null;

	@Autowired
	private UserService userService;
	@Autowired
	private TokenService tokenService;

	@Autowired
	private PermissionModuleService permissionModuleService;

	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof OAuth2Token;
	}

	/**
	 * 授权(验证权限时调用)
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		log.info("---------------- 执行 Shiro 权限获取 ---------------------");
		long start = System.currentTimeMillis();
		User loginUser = (User) principals.getPrimaryPrincipal();
		// Subject currentSubject = SecurityUtils.getSubject();
		String userId = loginUser.getId();
		if (ALL_MODULE == null || ALL_MODULE.isEmpty()) {
			// 所有可操作模块
			ALL_MODULE = permissionModuleService.findAllModuleCode();
		}
		if (ALL_FUNCTION == null || ALL_FUNCTION.isEmpty()) {
			// 所有可操作功能
			ALL_FUNCTION = permissionModuleService.findAllOperationCode();
		}
		if (ALL_FIELD == null || ALL_FIELD.isEmpty()) {
			// 所有敏感字段权限
			ALL_FIELD = permissionModuleService.findAllFieldCode();
		}

		// 用户权限列表
		Set<String> permsSet = new HashSet<String>();
		permsSet.add("test");

		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		// 获取当前用户所有的角色设置给authorizationInfo
		if (loginUser.getSysManager()) {
			// 当前用户只有除权限管理功能
			if (ALL_MODULE != null && !ALL_MODULE.isEmpty()) {
				authorizationInfo.addStringPermissions(ALL_MODULE);
			}
			if (ALL_FUNCTION != null && !ALL_FUNCTION.isEmpty()) {
				authorizationInfo.addStringPermissions(ALL_FUNCTION);
			}
			if (ALL_FIELD != null && !ALL_FIELD.isEmpty()) {
				authorizationInfo.addStringPermissions(ALL_FIELD);
			}
		} else if (loginUser.getCompanyManager()) {
			// 当前用户拥有除权限管理外所有的权限功能
			if (ALL_MODULE != null && !ALL_MODULE.isEmpty()) {
				authorizationInfo.addStringPermissions(ALL_MODULE);
			}
			if (ALL_FUNCTION != null && !ALL_FUNCTION.isEmpty()) {
				authorizationInfo.addStringPermissions(ALL_FUNCTION);
			}
			if (ALL_FIELD != null && !ALL_FIELD.isEmpty()) {
				authorizationInfo.addStringPermissions(ALL_FIELD);
			}
		} else {
			// 用戶权限
			authorizationInfo.addStringPermissions(userService.getUserPermissions(userId));
		}
		authorizationInfo.setStringPermissions(permsSet);
		long end = System.currentTimeMillis();
		log.info("UserRealm获取授权耗费时间：" + (end - start) + "毫秒");
		log.info("---------------- 获取到以下权限 ----------------");
		log.info(authorizationInfo.getStringPermissions().toString());
		log.info("---------------- Shiro 权限获取成功 ----------------------");
		return authorizationInfo;
	}

	/**
	 * 认证(登录时调用)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String accessToken = null;
		TokenInfo tokenInfo = null;
		User user = null;
		accessToken = (String) token.getPrincipal();
		// 根据accessToken，查询用户信息
		TokenVerifyRequest request = new TokenVerifyRequest();
		request.setToken(accessToken);
		try {
			tokenInfo = tokenService.verifyToken(request);
		} catch (Exception e) {
			e.printStackTrace();
		}
		// token失效
		if (tokenInfo == null || tokenInfo.getExpireAt().getTime() < System.currentTimeMillis()) {
			throw new IncorrectCredentialsException("token失效，请重新登录");
		}
		// 查询用户信息
		user = userService.selectById(tokenInfo.getUserId());
		// 账号锁定
		if (user.getLock().equals("1")) {
			throw new LockedAccountException("账号已被锁定,请联系管理员");
		}
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, accessToken, getName());
		return info;
	}
}
